package cc.vv.baselibrary.util

import android.app.ActivityManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Handler
import android.text.TextUtils
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import java.util.regex.Pattern

/**
 * 关于APP相关的一些操作工具类
 * Created by sun.li on 2018/7/19.
 * @author sun.li
 */
class BaseAppUtil private constructor(){

    companion object {
        val instance = BaseAppUtil()
    }

    /**
     * 程序是否在前台运行
     *
     * @return
     */
    fun isAppOnForeground(context: Context): Boolean {
        val activityManager = context.applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val packageName =context.applicationContext.packageName
        val appProcesses = activityManager.runningAppProcesses ?: return false

        for (appProcess in appProcesses) {
            if (appProcess.processName == packageName && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return true
            }
        }
        return false
    }

    /**
     * 判断程序是否正在后台运行
     *
     * @return
     */
    fun isAppOnBackground(context: Context): Boolean {
        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val packageName = context.packageName
        if (activityManager == null) {
            return false
        }
        val processList = activityManager.getRunningTasks(100)
        for (info in processList) {
            if (info.topActivity.packageName.startsWith(packageName)) {
                return true
            }
        }
        return false
    }

    /**
     * 检测APK是否存在
     *
     * @return
     */
    fun checkPackage(context: Context): Boolean {
        var flag = false
        try {
            val packageManager = context.packageManager
            val packageName = context.packageName
            val packageInfo = packageManager.getPackageInfo(packageName, 0)
            if (null != packageInfo) {
                flag = true
            }
        } catch (e: PackageManager.NameNotFoundException) {
            flag = false
            LKLogUtil.e(e.message, e)
        }

        return flag
    }

    /**
     * 打开App
     */
    fun openApp(context: Context) {
        try {
            val packageName = context.packageName
            val packageManager =context.packageManager
            val packageInfo = packageManager.getPackageInfo(packageName, 0)
            val resolveIntent = Intent(Intent.ACTION_MAIN, null)
            resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER)
            resolveIntent.`package` = packageInfo.packageName
            val apps = packageManager.queryIntentActivities(resolveIntent, 0)

            val ri = apps.iterator().next()
            if (ri != null) {
                val className = ri!!.activityInfo.name

                val intent = Intent(Intent.ACTION_MAIN)
                intent.addCategory(Intent.CATEGORY_LAUNCHER)

                val cn = ComponentName(packageName, className)

                intent.component = cn
                context.startActivity(intent)
            }
        } catch (e: PackageManager.NameNotFoundException) {
            LKLogUtil.e(e.message, e)
        }


    }


    /**
     * 获取版本号
     */
    fun checkVersionCode(context: Context): Int {
        val packageManager = context.packageManager
        try {
            val packInfo = packageManager.getPackageInfo(context.packageName, 0)
            return packInfo.versionCode
        } catch (e: PackageManager.NameNotFoundException) {
            LKLogUtil.e(e.message, e)
        }

        return 0
    }

    /**
     * 获取版本信息
     */
    fun checkVersionInfo(context: Context): String {
        val vsersionName = ""
        val packageManager = context.packageManager
        try {
            val packInfo = packageManager.getPackageInfo(context.packageName, 0)
            if (packInfo != null) {
                if (!TextUtils.isEmpty(packInfo!!.versionName)) {
                    return vsersionName
                }
            }
        } catch (e: PackageManager.NameNotFoundException) {
            LKLogUtil.e(e.message, e)
        }

        return vsersionName
    }

    /**
     * 获取安装包中logo
     *
     * @param apkPath
     * @return
     */
    fun getApkIcon(context: Context,apkPath: String): Drawable? {
        val pm = context.packageManager
        val info = pm.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES)
        if (null != info) {
            val applicationInfo = info!!.applicationInfo
            applicationInfo.sourceDir = apkPath
            applicationInfo.publicSourceDir = apkPath
            try {
                return pm.getApplicationIcon(applicationInfo)
            } catch (e: OutOfMemoryError) {
                LKLogUtil.e(e.message, e)
            }

        }
        return null
    }

    /**
     * 获取APP包名
     *
     * @return
     */
    fun getAppName(context: Context): String? {
        val pid = android.os.Process.myPid()
        var processName: String? = null
        val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val l = am.runningAppProcesses
        val i = l.iterator()
        while (i.hasNext()) {
            val info = i.next() as ActivityManager.RunningAppProcessInfo
            try {
                if (info.pid == pid) {
                    processName = info.processName
                    return processName
                }
            } catch (e: Exception) {
                LKLogUtil.e(e.message, e)
            }

        }
        return processName
    }


    fun isShouldHideInput(v: View?, event: MotionEvent): Boolean {
        if (v != null && v is EditText) {
            val leftTop = intArrayOf(0, 0)
            //获取输入框当前的location位置
            v.getLocationInWindow(leftTop)
            val left = leftTop[0]
            val top = leftTop[1]
            val bottom = top + v.height
            val right = left + v.width
            return if (event.x > left && event.x < right
                    && event.y > top && event.y < bottom) {
                // 点击的是输入框区域，保留点击EditText的事件
                false
            } else {
                true
            }
        }
        return false
    }

    /**
     * 自动默认弹起键盘弹起键盘
     */
    fun openInputLogin(ed: EditText, mHandler: Handler) {
        ed.isFocusable = true
        ed.isFocusableInTouchMode = true
        ed.requestFocus()
        mHandler.postDelayed({
            val inputManager = ed.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            inputManager.showSoftInput(ed, 0)
        }, 300)
    }


    /**
     * 弹起键盘
     */
    fun openInput(ed: EditText) {
        val inputManager = ed.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        inputManager.showSoftInput(ed, 0)
    }


    /**
     * 关闭输入法
     */
    fun closeInput(context: Context, ed: EditText) {
        val inputManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        val isOpen = inputManager.isActive
        if (isOpen) {
            inputManager.hideSoftInputFromWindow(ed.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
        }
    }

    /**
     * 关闭输入法
     */
    fun closeInput(context: Context, view: View) {
        val inputManager = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        val isOpen = inputManager.isActive
        if (isOpen) {
            inputManager.hideSoftInputFromWindow(view.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
        }
    }

    /**
     * 判断字符串是否是浮点数
     */
    fun isDouble(value: String): Boolean {
        try {
            java.lang.Double.parseDouble(value)
            return if (value.contains(".")) true else false
        } catch (e: NumberFormatException) {
            return false
        }

    }

    /**
     * 判断字符串是否为纯数字
     */
    fun isIntegerNum(str: String): Boolean {
        if (TextUtils.isEmpty(str)) {
            return false
        }
        val regex = "^[0-9]+(.[0-9]+)?$"
        return if (str.matches(regex.toRegex())) {
            true
        } else {
            false
        }
    }

    private val pattern = Pattern.compile("[0-9]*")

    /**
     * 判断字符串是否为纯数字
     */
    fun isNumeric(str: String): Boolean {

        val isNum = pattern.matcher(str)
        return if (!isNum.matches()) {
            false
        } else true
    }

    fun containsEmoji(source: String): Boolean {
        val len = source.length
        for (i in 0 until len) {
            val codePoint = source[i]
            //如果不能匹配,则该字符是Emoji表情
            if (!isEmojiCharacter(codePoint)) {
                return true
            }
        }
        return false
    }

    /**
     * 判断是否是Emoji
     *
     * @param codePoint 比较的单个字符
     * @return
     */
    private fun isEmojiCharacter(codePoint: Char): Boolean {

        return codePoint.toInt() == 0x0 || codePoint.toInt() == 0x9 || codePoint.toInt() == 0xA ||
                codePoint.toInt() == 0xD || codePoint.toInt() >= 0x20 && codePoint.toInt() <= 0xD7FF ||
                codePoint.toInt() >= 0xE000 && codePoint.toInt() <= 0xFFFD || codePoint.toInt() >= 0x10000 && codePoint.toInt() <= 0x10FFFF
    }

    /**
     * 判断某个服务是否正在运行的方法
     *
     * @param mContext
     * @param serviceName 是包名+服务的类名（例如：net.loonggg.testbackstage.TestService）
     * @return true代表正在运行，false代表服务没有正在运行
     */
    fun isServiceWork(mContext: Context, serviceName: String): Boolean {
        var isWork = false
        val myAM = mContext
                .getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val myList = myAM.getRunningServices(40)
        if (myList.size <= 0) {
            return false
        }
        for (i in myList.indices) {
            val mName = myList[i].service.className.toString()
            if (mName == serviceName) {
                isWork = true
                break
            }
        }
        return isWork
    }
}